﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using TranslatorService.Speech;
using System.Globalization;

namespace TranslatorService.Example
{
    public partial class MainPage : PhoneApplicationPage
    {
        private bool loaded = false;

        private const string CLIENT_ID = "";
        private const string CLIENT_SECRET = "";

        private SpeechSynthesizer speech;

        // Constructor
        public MainPage()
        {
            InitializeComponent();

            if (string.IsNullOrEmpty(CLIENT_ID) || string.IsNullOrEmpty(CLIENT_SECRET))
            {
                MessageBox.Show("You must obtain a Client ID and Secret in order to use this application. Please visit Azure DataMarket at https://datamarket.azure.com/developer/applications to get one.\r\nThen, go to https://datamarket.azure.com/dataset/1899a118-d202-492c-aa16-ba21c33c06cb and subscribe the Microsoft Translator Service.", this.Title, MessageBoxButton.OK);
                this.IsEnabled = false;
                return;
            }

            // Create the object that retrieves speech streams.
            speech = new SpeechSynthesizer(CLIENT_ID, CLIENT_SECRET);
            speech.AudioFormat = SpeakStreamFormat.Wave;
            speech.AudioQuality = SpeakStreamQuality.MaxQuality;
            speech.AutoDetectLanguage = true;
            speech.AutomaticTranslation = true;

            speech.GetLanguagesCompleted += new EventHandler<GetLanguagesEventArgs>(speech_GetLanguagesCompleted);
            speech.SpeakFailed += new EventHandler<SpeechEventArgs>(speech_SpeakFailed);
            speech.TranslateCompleted += new EventHandler<TranslateEventArgs>(speech_TranslateCompleted);
            speech.DetectLanguageCompleted += new EventHandler<DetectLanguageEventArgs>(speech_DetectLanguageCompleted);
        }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            if (!loaded && speech != null)
            {
                this.StartElaboration();

                // Retrieves the list of supported languages.
                speech.GetLanguagesAsync();
                loaded = true;
            }
        }

        private void chkAudoDetect_Click(object sender, RoutedEventArgs e)
        {
            lstLanguages.IsEnabled = !chkAudoDetect.IsChecked.Value;
            chkAutomaticTranslation.IsEnabled = !chkAudoDetect.IsChecked.Value;
        }

        private void speech_GetLanguagesCompleted(object sender, GetLanguagesEventArgs e)
        {
            this.FinishElaboration(e.Error);
            if (e.Error == null)
            {
                var languages = new Dictionary<string, string>();
                // This loop is necessary because some languages retrieved by the GetLanguages methods aren't supported
                // by Windows Phone.
                foreach (var language in e.Languages)
                {
                    try
                    {
                        var culture = new CultureInfo(language);
                        if (!culture.IsNeutralCulture)
                            languages.Add(language, culture.DisplayName);
                    }
                    catch { }
                }

                lstLanguages.ItemsSource = languages.OrderBy(i => i.Value);
                lstLanguages.SelectedItem = languages.Where(language => language.Value == CultureInfo.CurrentUICulture.DisplayName).FirstOrDefault();
            }
        }

        private void speech_SpeakFailed(object sender, SpeechEventArgs e)
        {
            string message = "An error occurred during speaking: " + e.Error.Message;
            MessageBox.Show(message);
        }

        private void speech_TranslateCompleted(object sender, TranslateEventArgs e)
        {
            this.FinishElaboration(e.Error);
            if (e.Error == null)
                txtTranslatedText.Text = e.TranslatedText;
        }

        private void speech_DetectLanguageCompleted(object sender, DetectLanguageEventArgs e)
        {
            this.FinishElaboration(e.Error);
            if (e.Error == null)
            {
                string message = string.Format("The language of the text is {0} - {1}", e.Language, new CultureInfo(e.Language).DisplayName);
                MessageBox.Show(message);
            }
        }

        private void btnSpeak_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtText.Text))
                return;

            speech.AutoDetectLanguage = chkAudoDetect.IsChecked.Value;
            speech.AutomaticTranslation = chkAutomaticTranslation.IsChecked.Value;

            // If auto language detection is enabled, don't use the selected language, because it will be auto-detected.
            string language = speech.AutoDetectLanguage ? null : ((KeyValuePair<string,string>)lstLanguages.SelectedItem).Key;

            speech.SpeakAsync(txtText.Text, language);
        }

        private void btnTranslate_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtText.Text))
                return;

            this.StartElaboration();
            speech.TranslateAsync(txtText.Text, ((KeyValuePair<string, string>)lstLanguages.SelectedItem).Key); 
        }

        private void btnDetectLanguage_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(txtText.Text))
                return;

            this.StartElaboration();
            speech.DetectLanguageAsync(txtText.Text);  
        }

        #region Helper methods

        private void StartElaboration()
        {
            pbrWaiting.IsIndeterminate = true;
        }

        private void FinishElaboration(Exception error)
        {
            pbrWaiting.IsIndeterminate = false;
            if (error != null)
                MessageBox.Show(error.Message);
        }

        #endregion
    }
}